#include "cet_util.h"
#include "garmin_fs.h"
#include <math.h>
-#if HAVE_LIBEXPAT
+#if HAVE_LIBEXPAT && !defined(NEW_GPX_READER)
#include <expat.h>
static XML_Parser psr;
+#else
+#include <QtCore/QXmlStreamReader>
+static QXmlStreamReader* reader;
#endif
#include "src/core/file.h"
#include "src/core/xmlstreamwriter.h"
static waypoint* wpt_tmp;
static UrlLink* link_;
static int cache_descr_is_html;
+#ifndef NEW_GPX_READER
static gbfile* fd;
+#else
+static gpsbabel::File* iqfile;
+#endif
static gpsbabel::File* oqfile;
static gpsbabel::XmlStreamWriter* writer;
static short_handle mkshort_handle;
}
}
+#ifndef NEW_GPX_READER
static void
tag_gpx(const char** attrv)
{
}
}
}
+#else
+static void
+tag_gpx(const QXmlStreamAttributes& attr)
+{
+ if (attr.hasAttribute("version")) {
+ /* Set the default output version to the highest input
+ * version.
+ */
+ if (! gpx_version) {
+ gpx_version = xstrdup(CSTR(attr.value("version").toString()));
+ } else if ((strtod(gpx_version, NULL) * 10) < (attr.value("version").toString().toDouble() * 10)) {
+ xfree(gpx_version);
+ gpx_version = xstrdup(CSTR(attr.value("version").toString()));
+ }
+ }
+ if (attr.hasAttribute("src")) {
+ /* TODO: this is unused */
+ /* FIXME: this data may be deallocated */
+ gpx_creator = CSTR(attr.value("src").toString());
+ }
+ /* save namespace declarations in case we pass through elements
+ * that use them to the writer.
+ */
+ const QXmlStreamNamespaceDeclarations ns = reader->namespaceDeclarations();
+ for (int i = 0; i < ns.size(); ++i) {
+ QString prefix = ns[i].prefix().toString();
+ QString namespaceUri = ns[i].namespaceUri().toString();
+ if (!prefix.isEmpty() && (0 != prefix.compare("xsi"))) {
+ if (! gpx_namespace_attribute.hasAttribute(prefix)) {
+ gpx_namespace_attribute.append(prefix.prepend("xmlns:"), namespaceUri);
+ }
+ }
+ }
+}
+#endif
+#ifndef NEW_GPX_READER
static void
tag_wpt(const char** attrv)
{
}
fs_ptr = &wpt_tmp->fs;
}
+#else
+static void
+tag_wpt(const QXmlStreamAttributes& attr)
+{
+ wpt_tmp = waypt_new();
+ link_ = new UrlLink;
+
+ cur_tag = NULL;
+ if (attr.hasAttribute("lat")) {
+ wpt_tmp->latitude = attr.value("lat").toString().toDouble();
+ }
+ if (attr.hasAttribute("lon")) {
+ wpt_tmp->longitude = attr.value("lon").toString().toDouble();
+ }
+ fs_ptr = &wpt_tmp->fs;
+}
+#endif
+#ifndef NEW_GPX_READER
static void
tag_cache_desc(const char** attrv)
{
}
}
}
+#else
+static void
+tag_cache_desc(const QXmlStreamAttributes& attr)
+{
+ cache_descr_is_html = 0;
+ if (attr.hasAttribute("html")) {
+ if (attr.value("html").toString().compare("True") == 0) {
+ cache_descr_is_html = 1;
+ }
+ }
+}
+#endif
+#ifndef NEW_GPX_READER
static void
tag_gs_cache(const char** attrv)
{
}
}
}
+#else
+static void
+tag_gs_cache(const QXmlStreamAttributes& attr)
+{
+ geocache_data* gc_data = waypt_alloc_gc_data(wpt_tmp);
+
+ if (attr.hasAttribute("id")) {
+ gc_data->id = attr.value("id").toString().toInt();
+ }
+ if (attr.hasAttribute("available")) {
+ if (attr.value("available").toString().compare("True", Qt::CaseInsensitive) == 0) {
+ gc_data->is_available = status_true;
+ } else if (attr.value("available").toString().compare("False", Qt::CaseInsensitive) == 0) {
+ gc_data->is_available = status_false;
+ }
+ }
+ if (attr.hasAttribute("archived")) {
+ if (attr.value("archived").toString().compare("True", Qt::CaseInsensitive) == 0) {
+ gc_data->is_archived = status_true;
+ } else if (attr.value("archived").toString().compare("False", Qt::CaseInsensitive) == 0) {
+ gc_data->is_archived = status_false;
+ }
+ }
+}
+#endif
static void
+#ifndef NEW_GPX_READER
start_something_else(const char* el, const char** attrv)
{
const char** avp = attrv;
avp++;
}
*avcp = NULL;
+#else
+start_something_else(const QString el, const QXmlStreamAttributes& attr)
+{
+ char** avcp;
+ int attr_count;
+ xml_tag* new_tag;
+ fs_xml* fs_gpx;
+
+ if (!fs_ptr) {
+ return;
+ }
+
+ new_tag = (xml_tag*)xcalloc(sizeof(xml_tag),1);
+ new_tag->tagname = xstrdup(CSTR(el));
+
+ attr_count = attr.size();
+ new_tag->attributes = (char**)xcalloc(sizeof(char*),2*attr_count+1);
+ avcp = new_tag->attributes;
+ for (int i = 0; i < attr_count; i++) {
+ *avcp = xstrdup(CSTR(attr[i].name().toString()));
+ avcp++;
+ *avcp = xstrdup(CSTR(attr[i].value().toString()));
+ avcp++;
+ }
+ *avcp = NULL; // this indicates the end of the attribute name value pairs.
+#endif
if (cur_tag) {
if (cur_tag->child) {
}
}
+#ifndef NEW_GPX_READER
static void
tag_log_wpt(const char** attrv)
{
waypt_add(lwp_tmp);
}
}
+#else
+static void
+tag_log_wpt(const QXmlStreamAttributes& attr)
+{
+ /* create a new waypoint */
+ waypoint* lwp_tmp = waypt_new();
+
+ /* extract the lat/lon attributes */
+ if (attr.hasAttribute("lat")) {
+ lwp_tmp->latitude = attr.value("lat").toString().toDouble();
+ }
+ if (attr.hasAttribute("lon")) {
+ lwp_tmp->longitude = attr.value("lon").toString().toDouble();
+ }
+ /* Make a new shortname. Since this is a groundspeak extension,
+ we assume that GCBLAH is the current shortname format and that
+ wpt_tmp refers to the currently parsed waypoint. Unfortunatley,
+ we need to keep track of log_wpt counts so we don't collide with
+ dupe shortnames.
+ */
+
+ if ((wpt_tmp->shortname) && (strlen(wpt_tmp->shortname) > 2)) {
+ /* copy of the shortname */
+ lwp_tmp->shortname = (char*) xcalloc(7, 1);
+ sprintf(lwp_tmp->shortname, "%-4.4s%02d",
+ &wpt_tmp->shortname[2], logpoint_ct++);
+
+ waypt_add(lwp_tmp);
+ }
+}
+#endif
static void
+#ifndef NEW_GPX_READER
gpx_start(void* data, const XML_Char* xml_el, const XML_Char** xml_attr)
+#else
+gpx_start(const QString& el, const QXmlStreamAttributes& attr)
+#endif
{
int passthrough;
int tag;
+#ifndef NEW_GPX_READER
const char* el = xml_convert_to_char_string(xml_el);
const char** attr = xml_convert_attrs_to_char_string(xml_attr);
current_tag.append("/");
current_tag.append(el);
+#endif
/*
tag_wpt(attr);
break;
case tt_wpt_link:
+#ifndef NEW_GPX_READER
if (attr[0] && attr[1] && 0 == strcmp(attr[0], "href")) {
link_url = xstrdup(attr[1]);
}
+#else
+ if (attr.hasAttribute("href")) {
+ link_url = xstrdup(CSTR(attr.value("href").toString()));
+ }
+#endif
break;
case tt_rte:
rte_head = route_head_alloc();
tag_cache_desc(attr);
break;
case tt_cache_placer:
+#ifndef NEW_GPX_READER
if (*attr && (0 == strcmp(attr[0], "id"))) {
waypt_alloc_gc_data(wpt_tmp)->placer_id = atoi(attr[1]);
}
+#else
+ if (attr.hasAttribute("id")) {
+ waypt_alloc_gc_data(wpt_tmp)->placer_id = attr.value("id").toString().toInt();
+ }
+#endif
default:
break;
}
if (passthrough) {
start_something_else(el, attr);
}
+#ifndef NEW_GPX_READER
xml_free_converted_string(el);
xml_free_converted_attrs(attr);
+#endif
}
struct
}
static void
+#ifndef NEW_GPX_READER
gpx_end(void* data, const XML_Char* xml_el)
+#else
+gpx_end(const QString& el)
+#endif
{
+#ifndef NEW_GPX_READER
const char* el = xml_convert_to_char_string(xml_el);
+#endif
int pos = current_tag.lastIndexOf('/');
QString s = current_tag.mid(pos + 1);
float x;
tag_type tag;
if (s.compare(el)) {
+#ifndef NEW_GPX_READER
fprintf(stderr, "Mismatched tag %s. Expected %s\n", el, qPrintable(s));
+#else
+// TODO: I don't think this is necesary with QXmlStreamReader
+ fprintf(stderr, "Mismatched tag %s. Expected %s\n", CSTR(el), qPrintable(s));
+#endif
}
tag = get_tag(current_tag, &passthrough);
break;
case tt_unknown:
end_something_else();
+#ifndef NEW_GPX_READER
current_tag.truncate(pos);
+#endif
return;
default:
break;
end_something_else();
}
+#ifndef NEW_GPX_READER
current_tag.truncate(pos);
xml_free_converted_string(el);
+#endif
}
-#if ! HAVE_LIBEXPAT
+#if ! HAVE_LIBEXPAT && !defined(NEW_GPX_READER)
static void
gpx_rd_init(const char* fname)
{
#else /* NO_EXPAT */
static void
+#ifndef NEW_GPX_READER
gpx_cdata(void* dta, const XML_Char* xml_el, int len)
+#else
+gpx_cdata(const char* s)
+#endif
{
char* estr;
int* cdatalen;
char** cdata;
xml_tag* tmp_tag;
size_t slen = strlen(cdatastr.mem);
+#ifndef NEW_GPX_READER
const char* s = xml_convert_to_char_string_n(xml_el, &len);
+#else
+ int len = strlen(s);
+#endif
vmem_realloc(&cdatastr, 1 + len + slen);
estr = ((char*) cdatastr.mem) + slen;
*(estr+len) = '\0';
*cdatalen += len;
+#ifndef NEW_GPX_READER
xml_free_converted_string(s);
+#endif
}
static void
gpx_rd_init(const char* fname)
{
+#ifndef NEW_GPX_READER
fd = gbfopen(fname, "r", MYNAME);
+#else
+ iqfile = new gpsbabel::File(fname);
+ iqfile->open(QIODevice::ReadOnly);
+ reader = new QXmlStreamReader(iqfile);
+#endif
current_tag.clear();
prescan_tags();
+#ifndef NEW_GPX_READER
psr = XML_ParserCreate(NULL);
if (!psr) {
fatal(MYNAME ": Cannot create XML Parser\n");
}
XML_SetUnknownEncodingHandler(psr, cet_lib_expat_UnknownEncodingHandler, NULL);
+#endif
cdatastr = vmem_alloc(1, 0);
*((char*)cdatastr.mem) = '\0';
QUEUE_INIT(&gpx_global->keywords.queue);
}
+#ifndef NEW_GPX_READER
XML_SetElementHandler(psr, gpx_start, gpx_end);
XML_SetCharacterDataHandler(psr, gpx_cdata);
+#endif
fs_ptr = NULL;
}
{
vmem_free(&cdatastr);
+#ifndef NEW_GPX_READER
if (fd) {
gbfclose(fd);
}
XML_ParserFree(psr);
psr = NULL;
+#else
+ delete reader;
+ reader = NULL;
+ iqfile->close();
+ delete iqfile;
+ iqfile = NULL;
+#endif
wpt_tmp = NULL;
cur_tag = NULL;
}
void
gpx_read(void)
{
-#if HAVE_LIBEXPAT
+#if HAVE_LIBEXPAT && !defined(NEW_GPX_READER)
int len;
char* buf = (char*) xmalloc(MY_CBUF_SZ);
}
}
xfree(buf);
-#endif /* HAVE_LIBEXPAT */
+#else
+ while (!reader->atEnd()) {
+ reader->readNext();
+ // do processing
+ switch (reader->tokenType()) {
+ case QXmlStreamReader::StartElement:
+ current_tag.append("/");
+ current_tag.append(reader->qualifiedName());
+
+ {
+ const QXmlStreamAttributes attrs = reader->attributes();
+ gpx_start(reader->qualifiedName().toString(), attrs);
+ }
+ break;
+
+ case QXmlStreamReader::EndElement:
+ gpx_end(reader->qualifiedName().toString());
+ current_tag.chop(reader->qualifiedName().length() + 1);
+ break;
+
+ case QXmlStreamReader::Characters:
+// It is tempting to skip this if reader->isWhitespace().
+// That would lose all whitespace element values if the exist,
+// but it would skip line endings and indentation that doesn't matter.
+ gpx_cdata(CSTR(reader->text().toString()));
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (reader->hasError()) {
+ fatal(MYNAME ":Read error: %s (%s, line %ld, col %ld)\n",
+ CSTR(reader->errorString()),
+ CSTR(iqfile->fileName()),
+ (long) reader->lineNumber(),
+ (long) reader->columnNumber());
+ }
+#endif /* USE_LIBEXPAT */
}
static void